package com.yeeKa.common;


import com.yeeKa.domain.Lock1518;
import com.yeeKa.utils.IpUtils;
import lombok.SneakyThrows;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Field;
import java.util.Arrays;

import static com.yeeKa.utils.PageUtil.getRequestAttributes;

/**
 * @author win10
 */
@Configuration
@Aspect
public class BeforeLog {
    private static final Logger log = LoggerFactory.getLogger(BeforeLog.class);
    @Before(value = "within(com.yeeKa.controller.*)")
    public void before(JoinPoint joinPoint){
        String ipStr = getRequestAttributes().getRequest().getRemoteAddr();
        Object[] args = joinPoint.getArgs();
        String ipFrom = IpUtils.getIpAddr(getRequestAttributes().getRequest());
        log.info("IpFrom: " + ipFrom);
        log.info("RemoteAdder: " + ipStr + ": "+joinPoint.getTarget().getClass().getName()+ ": "+joinPoint.getSignature().getName());
        log.info("args: "+ Arrays.toString(args));
    }



    /**设置切点方法或者类.*/
    @Pointcut("execution(* com.yeeKa.controller.InterlockingRecordsController.add(..))")
    public void getPointcut() {}


    /**对切点方法进行前置增强，就是在调用切点方法前进行做一些必要的操作，这就成为增强.*/
    @Before("getPointcut()")
    public void setDefaultValue(JoinPoint joinPoint){
        log.info("Before InterlockingRecordsController.add");
        for (Object arg : joinPoint.getArgs()) {
            if (arg instanceof Lock1518) {
                //获取字段域
                Field[] fields = arg.getClass().getDeclaredFields();
                setDefaultValue(fields,arg,"appearance");
                setDefaultValue(fields,arg,"functionality");
                setDefaultValue(fields,arg,"structure");
                log.info("Lock1518: {}", arg);
            }
        }
    }

    @SneakyThrows
    private void setDefaultValue(Field[] fields, Object arg, String theName) {
        //判断入参中是否有"theName"
        if (Arrays.stream(fields).noneMatch(item -> theName.equals(item.getName()))) {
            log.info("no theName field!");
        }
        try {
            Field field = arg.getClass().getDeclaredField(theName);
            field.setAccessible(true);
            if (null == field.get(arg) ){
                //将name参数替换为system
                field.set(arg, true);
            }else {
                field.set(arg, false);
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    /**用于配置后置通知。指定增强的方法在切入点方法之后执行，这个方式一定可以拦截到切点方法的返回值，@After拦截不到返回值.*/
    @AfterReturning(value = "getPointcut()", returning = "result")
    public void getResult(Object result) {
        log.debug("AfterReturning Intercept request");
        log.debug("result: {}", result);
    }

    /**用于配置最终通知。无论切入点方法执行时是否有异常，都会执行，只能拦截到入参.*/
    @After("getPointcut()")
    public void afterTest(JoinPoint joinPoint) {
        log.debug("After Intercept request");
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            log.debug("arg: {}", arg);
        }
    }
}
